/**
 * 
 */
package de.fsujena.chat_pi.connection;

import java.io.*;
import java.net.*;

import de.fsujena.chat_pi.message.Message;

/**
 * @author Erik Hebestreit
 * 
 */
public class Connector {
	Socket socket;
	boolean useRSA;
	boolean isClient;
	public RSAencryption rsaEnc;

	InputStream in;
	OutputStream out;

	InputStreamReader isr;
	OutputStreamWriter osw;

	public ObjectInputStream ois;
	public ObjectOutputStream oos;

	public BufferedReader bin;
	public BufferedWriter bout;

	public PrintWriter pout;

	/**
	 * 
	 */
	public Connector(Socket socket, boolean useRSA, boolean isClient) {
		this.socket = socket;
		this.useRSA = useRSA;
		this.isClient = isClient;

		if (useRSA) {
			rsaEnc = new RSAencryption();
		}
	}

	public boolean init() {
		try {
			in = socket.getInputStream();
			out = socket.getOutputStream();
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}

		isr = new InputStreamReader(in);
		osw = new OutputStreamWriter(out);

		bin = new BufferedReader(isr);
		bout = new BufferedWriter(osw);
		if (isClient) {
			try {
				ois = new ObjectInputStream(in);
				oos = new ObjectOutputStream(out);
				oos.flush();
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}
		} else {
			try {
				oos = new ObjectOutputStream(out);
				ois = new ObjectInputStream(in);
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}
		}

		if (useRSA) {
			if (isClient) {
				rsaEnc.receivePublicKey(ois);
				rsaEnc.sendPublicKey(oos);
			} else {
				rsaEnc.sendPublicKey(oos);
				rsaEnc.receivePublicKey(ois);
			}

			rsaEnc.initializeCipherStreams(in, out);

			in = rsaEnc.cis;
			out = rsaEnc.cos;
		} else {

		}

		pout = new PrintWriter(out, true);
		
		return true;
	}

	public boolean setRSA(Boolean useRSA) {
		this.useRSA = useRSA;
		init();

		return useRSA;
	}

	public boolean getRSA() {
		return useRSA;
	}

	public void sendString(String message) {
		pout.println(message);
	}

	public Object readGeneralObject() throws ClassNotFoundException,IOException {
		Object inputObject = null;
		// removed try/catch and added throws to simplify error handling

		inputObject = ois.readObject();

		return inputObject;
	}

	public String readStringObject() {
		String input = null;
		Object inputObject;
		try {
			inputObject = readGeneralObject();
			if (inputObject instanceof String)
				input = (String) inputObject;

			return input;
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return null;
	}

	public boolean sendStringObject(String outputString) {
		try {
			this.oos.writeObject(outputString);
			this.oos.flush();
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	public boolean sendObject(Object obj) {
		try {
			this.oos.writeObject(obj);
			this.oos.flush();
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	public Message readMessageObject() {
		Message message = null;
		Object inputObject;
		try {
			inputObject = readGeneralObject();
			if (inputObject instanceof Message)
				message = (Message) inputObject;

			return message;
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return null;
	}

	public boolean sendMessageObject(Message message) {
		try {
			this.oos.writeObject(message);
			this.oos.flush();
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

}
